#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <locale.h>

static void hexdump(const unsigned char *buf, size_t len)
{
    for (size_t i = 0; i < len; i += 16) {
        printf("%06zx  ", i);
        for (size_t j = 0; j < 16; ++j) {
            if (i + j < len) printf("%02x ", buf[i + j]);
            else             printf("   ");
        }
        printf(" |");
        for (size_t j = 0; j < 16 && i + j < len; ++j) {
            unsigned char c = buf[i + j];
            putchar(c >= 32 && c < 127 ? c : '.');
        }
        puts("|");
    }
}

int main(int argc, char *argv[])
{
    setlocale(LC_CTYPE, "");

    int port = argc > 1 ? atoi(argv[1]) : 8080;

    int srv = socket(AF_INET, SOCK_STREAM, 0);
    int opt = 1;
    setsockopt(srv, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(srv, (struct sockaddr *)&addr, sizeof(addr)) < 0 ||
        listen(srv, 10) < 0) {
        perror("bind/listen"); return 1;
    }

    printf("Listening on 0.0.0.0:%d\n", port);

    while (1) {
        int cli = accept(srv, NULL, NULL);
        if (cli < 0) { perror("accept"); continue; }

        char buf[4096];
        ssize_t n = recv(cli, buf, sizeof(buf), 0);
        if (n <= 0) { close(cli); continue; }

        puts("\n========== Hex Dump ==========");
        hexdump((unsigned char *)buf, n);
        puts("\n========== UTF-8 Text ==========");
        fwrite(buf, 1, n, stdout);
        fflush(stdout);

        const char *rsp =
            "HTTP/1.1 200 OK\r\n"
            "Content-Type: text/plain; charset=utf-8\r\n"
            "Connection: close\r\n\r\n"
            "OK - request dumped on server console\n";
        send(cli, rsp, strlen(rsp), 0);
        close(cli);
    }
}

